//////////////////////////////////////////////////////////////////////////
// trimap - class that use map container
// By Antonio Miranda - October 2010
//////////////////////////////////////////////////////////////////////////

#ifndef _TRI_MAP_H_
#define _TRI_MAP_H_

// includes
//----------
#include <algorithm>
#include <iostream>
#include <map>
using namespace std;

/*!
* CLASS
* mgIndexMap
*
* Class description.
*
* @author  
* @version
*/
//
//////////////////////////////////////////////////////////////////////////
class trimap
{
private:

  typedef struct key
  {
    int id[3];
  } Key;

  struct ltstr
  {
    bool operator()(const Key& s1, const Key& s2) const
    {
      if      (s1.id[0] < s2.id[0]) return 1;
      else if (s1.id[0] > s2.id[0]) return 0;
      else if (s1.id[1] < s2.id[1]) return 1;
      else if (s1.id[1] > s2.id[1]) return 0;
      else if (s1.id[2] < s2.id[2]) return 1;
      else if (s1.id[2] > s2.id[2]) return 0;
      else return 0;
    }
  };

  typedef map<const Key, void *, ltstr> TypeLocal;

  TypeLocal LocalMap;
  TypeLocal::iterator LocalInterator;

public:
  trimap ( ) { };
  ~trimap ( ) {clear ( );};

  // find method
  void *find (int id1, int id2, int id3)
  {
    Key copy;

    sort (id1, id2, id3, &copy.id[0], &copy.id[1], &copy.id[2]);

    LocalInterator = LocalMap.find (copy);

    if (LocalInterator == LocalMap.end ())
      return NULL;
    else
      return (LocalInterator->second);
  }

  // insert method
  void insert (int id1, int id2, int id3, void *info)
  {
    Key copy;

    sort (id1, id2, id3, &copy.id[0], &copy.id[1], &copy.id[2]);

    LocalMap.insert (make_pair(copy, info));
  }

  // find method
  void insert_delete ( int id1, int id2, int id3, void *info )
  {
    Key copy;

    sort (id1, id2, id3, &copy.id[0], &copy.id[1], &copy.id[2]);

    // try to insert new set of nodes
    LocalInterator = LocalMap.find (copy);

    // in case of not finding a pair => insert
    if (LocalInterator == LocalMap.end ())
      LocalMap.insert (make_pair(copy, info));
    else // delete
      LocalMap.erase(LocalInterator);
  }

  // sort id1, id2 and id3 to decrescent order
  void sort (int id1, int id2, int id3, int *n1, int *n2, int *n3)
  {
    if(id1>=id2 && id1>=id3)
    {
      *n3=id1;

      if(id2>=id3){*n2=id2; *n1=id3; }

      else {*n2=id3; *n1=id2;}
    }

    else if(id2>=id1 && id2>=id3)
    {
      *n3=id2;

      if(id1>=id3) { *n2=id1; *n1=id3; }

      else {*n2=id3; *n1=id1;}
    }

    else
    {
      *n3=id3;

      if(id1>=id2) { *n2=id1; *n1=id2; }

      else { *n2=id2; *n1=id1; }
    }
  }

  // get the number of entities
  int size() { return ((int) LocalMap.size ()); }

  // clear all
  void clear() { LocalMap.clear (); }

  // first entity
  void *first ( )
  {
    LocalInterator = LocalMap.begin( );
    return (LocalInterator->second);
  }

  // next entity
  void *next ( )
  {
    ++LocalInterator;
    if (LocalInterator == LocalMap.end ())
      return NULL;
    else
      return (LocalInterator->second);
  }

};

#endif
